package com.yummy.convention.date;

import java.text.ParseException;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Author Gino
 * @Description JDK8新特性修改
 * @Date 1:47 下午 2020/6/4
 * @Param
 * @return
 **/
public class DateUtil {

    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
    public static final String YYYY_MM_DD = "yyyy-MM-dd";
    public static final String YYYYMMDD = "yyyyMMdd";
    public static final String YYYY_MM = "yyyy-MM";
    public static final String YYYYMM = "yyyyMM";
    public static final String MMDD = "MMdd";
    public static final String YYYY_MM_DD_HH = "yyyy-MM-dd HH";
    public static final String YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
    public static final String YYYY_MM_DD_REPLACE = "yyyy.MM.dd";
    public static final String HH_MM_SS = "HH:mm:ss";
    public static final String HHMMSS = "HHmmss";
    public static final String YYYY = "yyyy";
    public static final String YMDHMS = "yMdHms";

    /**
     * @return java.lang.String
     * @Author Gino
     * @Description 日期转字符串
     * @Date 1:48 下午 2020/6/4
     * @Param [date]
     **/
    public static String dateToString(Date date) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(YYYY_MM_DD);
        LocalDateTime localDateTime = dateToLocalDT(date);
        return dateTimeFormatter.format(localDateTime);
    }

    /**
     * @return java.lang.String
     * @Author Gino
     * @Description 日期转字符串
     * @Date 1:48 下午 2020/6/4
     * @Param [date]
     **/
    public static String dateTimeToString(Date date) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS);
        LocalDateTime localDateTime = dateToLocalDT(date);
        return dateTimeFormatter.format(localDateTime);
    }

    /**
     * @return java.lang.String
     * @Author Gino
     * @Description 日期转任意格式字符串, s为格式定义
     * @Date 1:49 下午 2020/6/4
     * @Param [date, format]
     **/
    public static String dateToString(Date date, String format) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(format);
        LocalDateTime localDateTime = dateToLocalDT(date);
        return dateTimeFormatter.format(localDateTime);
    }

    /**
     * @Author Gino
     * @Description 字符串转日期
     * @Date 2:11 下午 2020/6/4
     * @Param [day]
     * @return java.util.Date
     **/
    public static Date stringToDate(String day) throws ParseException {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(YYYY_MM_DD);
        LocalDateTime dateTime = LocalDate.parse(day, dateTimeFormatter).atStartOfDay();
        return localDTToDate(dateTime);
    }

    /**
     * @Author Gino
     * @Description 字符串转日期
     * @Date 2:12 下午 2020/6/4
     * @Param [day, format]
     * @return java.util.Date
     **/
    public static Date stringToDate(String day, String format) throws ParseException {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(format);
        LocalDateTime dateTime = LocalDateTime.parse(day, dateTimeFormatter);
        return localDTToDate(dateTime);
    }

    /**
     * @Author Gino
     * @Description 字符串转日期时间
     * @Date 2:12 下午 2020/6/4
     * @Param [day]
     * @return java.util.Date
     **/
    public static Date stringToDateTime(String day) throws ParseException {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS);
        LocalDateTime dateTime = LocalDateTime.parse(day, dateTimeFormatter);
        return localDTToDate(dateTime);
    }

    /**
     * @Author Gino
     * @Description 得到前几月
     * @Date 2:24 下午 2020/6/4
     * @Param [date, month]
     * @return java.util.Date
     **/
    public static Date getMonthBefore(Date date, int month) {
        LocalDateTime localDateTime = dateToLocalDT(date);
        LocalDateTime minus = localDateTime.minus(month, ChronoUnit.MONTHS);
        return localDTToDate(minus);
    }

    /**
     * @Author Gino
     * @Description 得到几月后
     * @Date 2:25 下午 2020/6/4
     * @Param [date, month]
     * @return java.util.Date
     **/
    public static Date getMonthAfter(Date date, int month) {
        LocalDateTime localDateTime = dateToLocalDT(date);
        LocalDateTime minus = localDateTime.plus(month, ChronoUnit.MONTHS);
        return localDTToDate(minus);
    }

    /**
     * @Author Gino
     * @Description 得到几天后
     * @Date 2:26 下午 2020/6/4
     * @Param [date, day]
     * @return java.util.Date
     **/
    public static Date getDateAfter(Date date, int day) {
        LocalDateTime localDateTime = dateToLocalDT(date);
        LocalDateTime minus = localDateTime.plus(day, ChronoUnit.DAYS);
        return localDTToDate(minus);
    }

    /**
     * @Author Gino
     * @Description 得到几天前
     * @Date 6:39 下午 2020/6/4
     * @Param [date, day]
     * @return java.util.Date
     **/
    public static Date getDateBefore(Date date, int day) {
        LocalDateTime localDateTime = dateToLocalDT(date);
        LocalDateTime minus = localDateTime.minus(day, ChronoUnit.DAYS);
        return localDTToDate(minus);
    }

    /**
     * @Author Gino
     * @Description 得到当天的星期
     * @Date 6:39 下午 2020/6/4
     * @Param []
     * @return int
     **/
    public final static int currentWeek() {
        return LocalDateTime.now().getDayOfWeek().getValue();
    }

    /**
     * @Author Gino
     * @Description 得到当前日期是周几
     * @Date 6:39 下午 2020/6/4
     * @Param [date]
     * @return int
     **/
    public final static int getWeek(Date date) {
        return dateToLocalDT(date).getDayOfWeek().getValue();
    }


    /**
     * @Author Gino
     * @Description 得到当前年份 2015
     * @Date 6:38 下午 2020/6/4
     * @Param []
     * @return java.lang.String
     **/
    public final static String currentYear() {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(YYYY);
        LocalDate localDateTime = LocalDate.now();
        return dateTimeFormatter.format(localDateTime);
    }

    /**
     * @Author Gino
     * @Description 得到当前年份和月份2012-05
     * @Date 6:38 下午 2020/6/4
     * @Param []
     * @return java.lang.String
     **/
    public final static String currentYearMonth() {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(YYYY_MM);
        LocalDate localDateTime = LocalDate.now();
        return dateTimeFormatter.format(localDateTime);
    }

    /**
     * @Author Gino
     * @Description 得到当前年份和月份的第一天2012-05-01
     * @Date 6:38 下午 2020/6/4
     * @Param []
     * @return java.lang.String
     **/
    public final static String currentYearMonthDay1st() {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(YYYY_MM_DD);
        LocalDate localDateTime = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
        return dateTimeFormatter.format(localDateTime);
    }

    /**
     * @Author Gino
     * @Description 得到当前年份和月份天2012-05-01
     * @Date 6:38 下午 2020/6/4
     * @Param []
     * @return java.lang.String
     **/
    public final static String currentYearMonthDay() {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(YYYY_MM_DD);
        LocalDate localDateTime = LocalDate.now();
        return dateTimeFormatter.format(localDateTime);
    }

    /**
     * @Author Gino
     * @Description 得到当前4位年份2位月份2位天20120501
     * @Date 6:37 下午 2020/6/4
     * @Param []
     * @return java.lang.String
     **/
    public final static String currentPureYearMonthDay() {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(YYYYMMDD);
        LocalDate localDateTime = LocalDate.now();
        return dateTimeFormatter.format(localDateTime);
    }

    /**
     * @Author Gino
     * @Description 得到当前2位月份2位天0501
     * @Date 6:36 下午 2020/6/4
     * @Param []
     * @return java.lang.String
     **/
    public final static String currentPureYearMonth() {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(MMDD);
        LocalDate localDateTime = LocalDate.now();
        return dateTimeFormatter.format(localDateTime);
    }

    /**
     * @Author Gino
     * @Description 得到当前6位 时分秒
     * @Date 6:36 下午 2020/6/4
     * @Param []
     * @return java.lang.String
     **/
    public final static String currentPureHourMinuteSecond() {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(HHMMSS);
        LocalTime localDateTime = LocalTime.now();
        return dateTimeFormatter.format(localDateTime);
    }

    /**
     * @Author Gino
     * @Description 得到当前年、月、日 时、分、秒 2012-05-01 8:16:39
     * @Date 6:36 下午 2020/6/4
     * @Param []
     * @return java.lang.String
     **/
    public final static String currentYearMonthDayTime() {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS);
        LocalDateTime localDateTime = LocalDateTime.now();
        return dateTimeFormatter.format(localDateTime);
    }

    /**
     * @Author Gino
     * @Description 得到当前年、月、日 时、分、秒 缩写
     * @Date 6:35 下午 2020/6/4
     * @Param []
     * @return java.lang.String
     **/
    public final static String currentYearMonthDayTimeShort() {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(YMDHMS);
        LocalDateTime localDateTime = LocalDateTime.now();
        return dateTimeFormatter.format(localDateTime);
    }

    /**
     * @Author Gino
     * @Description 得到当前时分秒
     * @Date 6:35 下午 2020/6/4
     * @Param []
     * @return java.lang.String
     **/
    public final static String currentTime() {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(HH_MM_SS);
        LocalTime localDateTime = LocalTime.now();
        return dateTimeFormatter.format(localDateTime);
    }

    /**
     * @Author Gino
     * @Description 比较两个日期时间的大小
     * @Date 6:35 下午 2020/6/4
     * @Param [time1, time2]
     * @return long
     **/
    public final static long compareTime(String time1, String time2) throws ParseException {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS);
        LocalDateTime dateTime1 = LocalDateTime.parse(time1, dateTimeFormatter);
        LocalDateTime dateTime2 = LocalDateTime.parse(time2, dateTimeFormatter);
        return compareTime(dateTime1,dateTime2);
    }

    /**
     * @Author Gino
     * @Description 比较两个日期
     * @Date 6:35 下午 2020/6/4
     * @Param [date1, date2]
     * @return long
     **/
    public final static long compareTime(Date date1, Date date2) {
        return compareTime(dateToLocalDT(date1),dateToLocalDT(date2));
    }

    /**
     * @Author Gino
     * @Description 比较两个日期
     * @Date 6:34 下午 2020/6/4
     * @Param [ldt1, ldt2]
     * @return long
     **/
    public final static long compareTime(LocalDateTime ldt1,LocalDateTime ldt2){
        Duration between = Duration.between(ldt1, ldt2);
        return between.toMillis();
    }

    /**
     * @Author Gino
     * @Description 得到当前年份和月份天2012-05-01
     * @Date 6:34 下午 2020/6/4
     * @Param [day]
     * @return java.lang.String
     **/
    public final static String currentYearMonthDayTime(int day) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS);
        LocalDateTime localDateTime = LocalDateTime.now().plusDays(day);
        return dateTimeFormatter.format(localDateTime);
    }

    /**
     * @Author Gino
     * @Description 得到某年月的第一天
     * @Date 6:34 下午 2020/6/4
     * @Param [year, month]
     * @return java.lang.String
     **/
    public final static String firstDayOfYearMonth(int year, int month) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(YYYY_MM_DD);
        LocalDate localDateTime = LocalDate.of(year,month,1);
        return dateTimeFormatter.format(localDateTime);
    }

    /**
     * @Author Gino
     * @Description 得到某年月的最后一天
     * @Date 6:34 下午 2020/6/4
     * @Param [year, month]
     * @return java.lang.String
     **/
    public final static String lastDayOfYearMonth(int year, int month) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(YYYY_MM_DD);
        LocalDate localDateTime = LocalDate.of(year,month,1).with(TemporalAdjusters.lastDayOfMonth());
        return dateTimeFormatter.format(localDateTime);
    }

    /**
     * @Author Gino
     * @Description 得到某年月的每一天
     * @Date 6:33 下午 2020/6/4
     * @Param [year, month]
     * @return java.lang.String[]
     **/
    public final static String[] daysOfYearMonth(int year, int month) {
        LocalDateTime start = LocalDateTime.of(year,month,1,0,0);
        LocalDateTime end = LocalDateTime.of(year,month,1,0,0).with(TemporalAdjusters.lastDayOfMonth());
        //总天数
        long totalDays = Duration.between(start, end).toDays() + 1;
        String[] days = new String[(int)totalDays];
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(YYYY_MM_DD);
        for(int i=0;i<totalDays;i++){
            days[i]=dateTimeFormatter.format(start.plusDays(i));
        }
        return days;
    }

    /**
     * @Author Gino
     * @Description 计算两个日期之间相差的天数
     * @Date 6:33 下午 2020/6/4
     * @Param [date1, date2]
     * @return long
     **/
    public final static long daysBetween(Date date1, Date date2) {
        LocalDateTime ldt1 = dateToLocalDT(date1);
        LocalDateTime ldt2 = dateToLocalDT(date2);
        Duration between = Duration.between(ldt1, ldt2);
        return between.toDays();
    }

    /**
     * @Author Gino
     * @Description 获取中文日期
     * @Date 6:33 下午 2020/6/4
     * @Param [w]
     * @return java.lang.String
     **/
    public final static String getChWeek(int w) {
        String r = "";
        switch (w) {
            case 1:
                r = "一";
                break;
            case 2:
                r = "二";
                break;
            case 3:
                r = "三";
                break;
            case 4:
                r = "四";
                break;
            case 5:
                r = "五";
                break;
            case 6:
                r = "六";
                break;
            case 7:
                r = "日";
                break;
        }
        return r;
    }

    /**
     * @Author Gino
     * @Description 获取当天的开始时间
     * @Date 6:33 下午 2020/6/4
     * @Param []
     * @return java.util.Date
     **/
    public static Date getDayBegin() {
        LocalDate date = LocalDate.now();
        LocalTime time = LocalTime.of(0, 0, 0);
        LocalDateTime dateTime = LocalDateTime.of(date, time);
        return localDTToDate(dateTime);
    }

    /**
     * @Author Gino
     * @Description 获取当天的结束时间
     * @Date 6:32 下午 2020/6/4
     * @Param []
     * @return java.util.Date
     **/
    public static Date getDayEnd() {
        LocalDate date = LocalDate.now();
        LocalTime time = LocalTime.of(23, 59, 59);
        LocalDateTime dateTime = LocalDateTime.of(date, time);
        return localDTToDate(dateTime);
    }

    /**
     * @Author Gino
     * @Description 获取昨天的开始时间
     * @Date 6:32 下午 2020/6/4
     * @Param []
     * @return java.util.Date
     **/
    public static Date getBeginDayOfYesterday() {
        LocalDate date = LocalDate.now().minusDays(1);
        LocalTime time = LocalTime.of(0, 0, 0);
        LocalDateTime dateTime = LocalDateTime.of(date, time);
        return localDTToDate(dateTime);
    }

    /**
     * @Author Gino
     * @Description 获取昨天的结束时间
     * @Date 6:32 下午 2020/6/4
     * @Param []
     * @return java.util.Date
     **/
    public static Date getEndDayOfYesterDay() {
        LocalDate date = LocalDate.now().minusDays(1);
        LocalTime time = LocalTime.of(23, 59, 59);
        LocalDateTime dateTime = LocalDateTime.of(date, time);
        return localDTToDate(dateTime);
    }

    /**
     * @Author Gino
     * @Description 获取一天的结束时间
     * @Date 6:32 下午 2020/6/4
     * @Param [date1]
     * @return java.util.Date
     **/
    public static Date getDateEnd(Date date1) {
        LocalDate date = dateToLocalD(date1);
        LocalTime time = LocalTime.of(23, 59, 59);
        LocalDateTime dateTime = LocalDateTime.of(date, time);
        return localDTToDate(dateTime);
    }

    /**
     * @Author Gino
     * @Description 获取一天的开始时间
     * @Date 6:31 下午 2020/6/4
     * @Param [date1]
     * @return java.util.Date
     **/
    public static Date getDateStart(Date date1) {
        LocalDate date = dateToLocalD(date1);
        LocalTime time = LocalTime.of(0, 0, 0);
        LocalDateTime dateTime = LocalDateTime.of(date, time);
        return localDTToDate(dateTime);
    }

    /**
     * @Author Gino
     * @Description 解析时间
     * @Date 6:31 下午 2020/6/4
     * @Param [time]
     * @return java.util.Date
     **/
    public static Date parse(String time) throws ParseException {
        try {
            return stringToDate(time, YYYY_MM_DD_HH_MM_SS);
        } catch (ParseException e) {
            try {
                return stringToDate(time, YYYY_MM_DD_HH_MM);
            } catch (ParseException e1) {
                try {
                    return stringToDate(time, YYYY_MM_DD_HH);
                } catch (ParseException e2) {
                    return stringToDate(time, YYYY_MM_DD);
                }
            }
        }
    }

    /**
     * @return java.time.LocalDateTime
     * @Author Gino
     * @Description date转localDateTime
     * @Date 2:07 下午 2020/6/4
     * @Param [date]
     **/
    public static LocalDateTime dateToLocalDT(Date date) {
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        return LocalDateTime.ofInstant(instant, zoneId);
    }

    /**
     * @Author Gino
     * @Description date转localDate
     * @Date 6:27 下午 2020/6/4
     * @Param [date]
     * @return java.time.LocalDate
     **/
    public static LocalDate dateToLocalD(Date date) {
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zoneId);
        return localDateTime.toLocalDate();
    }

    /**
     * @return java.util.Date
     * @Author Gino
     * @Description localDateTime转date
     * @Date 2:03 下午 2020/6/4
     * @Param [localDateTime]
     **/
    public static Date localDTToDate(LocalDateTime localDateTime) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDateTime.atZone(zoneId);
        return Date.from(zdt.toInstant());
    }

    /**
     * 日期按照x天拆分
     * @autor chishouwu
     * 2021 2021年4月16日
     */
	public static List<TimeSlot> splitInXD(Date begin, Date end, int x) {
		if(begin.compareTo(end) > 0) {
			return null;
		}
		List<TimeSlot> slots = new ArrayList<>();
		Date currentEndDate = DateUtil.getDateAfter(begin, x);
		if(currentEndDate.compareTo(end) >= 0) {
			currentEndDate = end;
		}
		Date currentBeginDate = begin;
		while(currentBeginDate.compareTo(end) <= 0) {
			TimeSlot slot = new TimeSlot();
			slot.setTimeEnd(currentEndDate);
			slot.setTimeStart(currentBeginDate);
			slots.add(slot);
			currentBeginDate = DateUtil.getDateAfter(currentEndDate,1);
			currentEndDate = DateUtil.getDateAfter(currentEndDate, x);
			if(currentEndDate.compareTo(end) >= 0) {
				currentEndDate = end;
			}
		}
		return slots;
	}
}
